<!DOCTYPE html>
<html>
<head>
  <title></title>
</head>
<body>
  <script>
    class Dep {
      constructor() {
        this.subcribers = new Set();
      }

      deep() {
        if (activeUpdate) {
          this.subcribers.add(activeUpdate);
        }
      }

      notify() {
        this.subcribers.forEach(sub => sub());
      }
    }

    let activeUpdate;

    function autorun(update) {
      function wrappedUpdate() {
        activeUpdate = wrappedUpdate;
        update();
        activeUpdate = null;
      }
      wrappedUpdate();
    }

    const state = {
      count: 0
    };

    const p = observe(state);

    autorun(() => {
      console.log(p.count);
    });

    function observe(obj) {
      const depMap = Object.create(null);
      Object.keys(obj).forEach(key => {
        depMap[key] = new Dep();
      });

      return new Proxy(obj, {
        get(target, prop) {
          depMap[prop].deep();
          return target[prop];
        },
        set(target, prop, value) {
          const changed = target[prop] !== value;
          target[prop] = value;
          if (changed) {
            depMap[prop].notify();
          }
        }
      });
    }
  </script>
</body>
</html>
